﻿using System;
using System.ComponentModel;
using FlexPlatform.Visual.Presenters;
namespace FlexPlatform.Visual.Presenters
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    
    using FlexPlatform.BusinessLogic.Controllers;
    using FlexPlatform.GeneralUse;
    using FlexPlatform.Shared.DataModel;
    using FlexPlatform.BusinessLogic;
    using FlexPlatform.BusinessLogic.Validation;

    public class EntityPresenter : SimplePresenter, ICustomTypeDescriptor
    {
        private IDataEntity clsDataEntity;

        private PropertyDescriptorCollection clsPropertyDescriptorCollectionCache;

        private Dictionary<string, PropertyPresenter> clsPropertiesPresenters;

        private IDataEntityController clsEntityController;
 
        public EntityPresenter(IDataEntity dataEntity)
        {
            this.clsDataEntity = dataEntity;

            // Create all the needed controllers

            // Create the EntityController
            clsEntityController = new DataEntityController(dataEntity);
            
            // create all properties of DataEntity as SimplePresenter(s)
            BuildUpPropertyPresenters();
        }

        internal PropertyPresenter GetPropertyPresenter(string propertyName)
        {
            return clsPropertiesPresenters[propertyName];
        }
       
        private void BuildUpPropertyPresenters()
        {
            int k = 0;
            clsPropertiesPresenters = new Dictionary<string, PropertyPresenter>();
            
            // for each property in DataEntity, create a SimplePresenter object
            var publicPropeties = ReflectionHelper.GetPropertyInfos(clsDataEntity.GetType());
            PropertyDescriptor[] properties = new PropertyDescriptor[publicPropeties.Count];
            
            foreach (var property in publicPropeties)
            {
                PropertyPresenter propertyPresenter = new PropertyPresenter(property.Name);
                clsPropertiesPresenters.Add(property.Name, propertyPresenter);

                // build-up property descriptors
                CustomPropertyDescriptor propertyDescriptor = new CustomPropertyDescriptor(property.Name);
                properties[k] = propertyDescriptor;
                k++;
            }

            clsPropertyDescriptorCollectionCache = new PropertyDescriptorCollection(properties);
        }

        #region ICustomTypeDescriptor related methods

        #region Relevant ICustomTypeDescriptor

        public string GetClassName()
        {
            return clsDataEntity.GetType().ToString() + "Presenter";
        }                         

        public PropertyDescriptorCollection GetProperties(System.Attribute[] attributes)
        {
            return clsPropertyDescriptorCollectionCache;
        }

        public PropertyDescriptorCollection GetProperties()
        {
            return ((ICustomTypeDescriptor)this).GetProperties(null);
        }

        public object GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }

        #endregion

        #region NotRelevant properties

        public AttributeCollection GetAttributes()
        {
            return null;
        }

        public TypeConverter GetConverter()
        {
            return null;
        }

        public EventDescriptor GetDefaultEvent()
        {
            return null;
        }

        public PropertyDescriptor GetDefaultProperty()
        {
            return null;
        }

        public object GetEditor(System.Type editorBaseType)
        {
            return null;
        }

        public EventDescriptorCollection GetEvents(System.Attribute[] attributes)
        {
            return null;
        }

        public EventDescriptorCollection GetEvents()
        {
            return null;
        }

        public string GetComponentName()
        {
            return null;
        }

        #endregion

        #endregion
    }
}

public class CustomPropertyDescriptor : PropertyDescriptor
{
    public CustomPropertyDescriptor(string propertyName)
        : base(propertyName, null)
    {
    
    }
    
    public override bool CanResetValue(object component)
    {
        return true;
    }
    
    public override Type ComponentType
    {
        get { return typeof(EntityPresenter); }
    }
    
    public override object GetValue(object component)
    {
        return ((EntityPresenter)component).GetPropertyPresenter(base.Name);
    }
    
    public override bool IsReadOnly
    {
        get { return true; }
    }
    
    public override Type PropertyType
    {
        get { return typeof(SimplePresenter); }
    }
    
    public override void ResetValue(object component)
    {
        this.SetValue(component, null);
    }
    
    public override void SetValue(object component, object value)
    {
        // nothing to do. The value is read-only.
    }
    
    public override bool ShouldSerializeValue(object component)
    {
        return false;
    }
}
